package com.pg_chat.utils;

import com.google.zxing.LuminanceSource;

/**
 * Author bai
 *
 * source https://zhuanlan.zhihu.com/p/164377752
 *
 */

import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;

public class BufferedImageLuminanceSource extends LuminanceSource {

    private final BufferedImage image;
    private final int left;
    private final int top;

    public BufferedImageLuminanceSource(BufferedImage image){
        this(image, 0, 0, image.getWidth(), image.getHeight());
    }

    public BufferedImageLuminanceSource(BufferedImage image, int left,
                                        int top, int width,
                                        int height) {
        super(width, height);

        int sourceWidth = image.getWidth();
        int sourceHeight = image.getHeight();
        if(left + width > sourceWidth || top + height > sourceHeight){
            throw new IllegalArgumentException("data error, cannot fit within image data");

        }

        for (int y =top; y < top + height; y++){
            for (int x = left; x < left + width; x++){
                if((image.getRGB(x,y) & 0xFF000000) == 0){
                    //QR Code background
                    image.setRGB(x, y, 0xFFFFFFFF);
                }
            }
        }

        this.image = new BufferedImage(sourceWidth, sourceHeight,
                BufferedImage.TYPE_BYTE_GRAY);
        this.image.getGraphics().drawImage(image, 0, 0, null);
        this.left = left;
        this.top = top;

    }

    @Override
    public boolean isCropSupported() {
        return true;
    }

    @Override
    public LuminanceSource crop(int left, int top, int width, int height) {
        return new BufferedImageLuminanceSource(this.image, this.left+left,
                this.top+top, width, height);
    }

    @Override
    public boolean isRotateSupported() {
        return true;
    }

    @Override
    public LuminanceSource invert() {
        return super.invert();
    }

    //
    @Override
    public LuminanceSource rotateCounterClockwise() {

        int sourceWidth = image.getWidth();
        int sourceHeight = image.getHeight();
        AffineTransform transform = new AffineTransform(0.0, -1.0,
                1.0, 0.0, 0.0, sourceWidth);
        BufferedImage rotatedImage = new BufferedImage(sourceHeight,
                sourceWidth, BufferedImage.TYPE_BYTE_GRAY);
        Graphics2D g = rotatedImage.createGraphics();
        g.drawImage(image, transform, null);
        g.dispose();
        int width = getWidth();
        return new BufferedImageLuminanceSource(rotatedImage, top,
                sourceWidth - (left + width), getHeight(), width);
    }

    @Override
    public LuminanceSource rotateCounterClockwise45() {
        return super.rotateCounterClockwise45();
    }

    @Override
    public byte[] getRow(int y, byte[] row) {
        if(y < 0 || y >= getHeight()){
            throw new IllegalArgumentException(
                    "Requested row is outside the image: " + y
            );
        }
        int width = getWidth();
        if(row == null || row.length < width){
            row = new byte[width];
        }
        image.getRaster().getDataElements(left, top + y,
                width, 1, row);
        return row;
    }

    @Override
    public byte[] getMatrix() {
        int width = getWidth();
        int height = getHeight();
        int area = width * height;
        byte[] matrix = new byte[area];
        image.getRaster().getDataElements(left, top, width, height, matrix);
        return matrix;
    }
}
